package fr.generali.accueilclient.gwt.client.state;

import com.google.gwt.core.client.Callback;
import com.google.web.bindery.event.shared.EventBus;

import fr.generali.accueilclient.gwt.client.state.event.LoadStateEvent;
import fr.generali.accueilclient.gwt.client.state.event.SaveStateEvent;

/**
 * Classe permettant à sauvegarder et à récupérer l'état d'un objet.
 * 
 * @param <S> L'interface de l'état.
 */
public class StateHandler<S, T> {

    private final Class<S> stateType;

    private final String stateId;

    private S currentState;

    private final StateManager stateManager;
    
    private final EventBus eventBus;
    
    private final T target;

    public StateHandler(StateManager stateManager, Class<S> stateType, T target, String stateId, EventBus eventBus) {
        assert stateType.isInterface();
        this.stateManager = stateManager;
        this.stateType = stateType;
        this.stateId = stateId;
        this.eventBus = eventBus;
        this.target = target;
    }

    /**
     * Retourne l'état courant. Appelez d'abord {@link #loadState(Callback)}
     * afin d'initialiser l'état courant.
     */
    public S getState() {
        if (currentState == null)
            throw new IllegalStateException("Appelez d'abord loadState(Callback)");
        return currentState;
    }

    /**
     * Starts to load the currentState for the given object.
     */
    public void loadState(final Callback<S, Throwable> callback) {
        stateManager.get(stateId, stateType, new Callback<S, Throwable>() {
            @Override
            public void onFailure(Throwable reason) {
                callback.onFailure(reason);
            }

            @Override
            public void onSuccess(S result) {
                currentState = result;
                callback.onSuccess(result);
                eventBus.fireEvent(new LoadStateEvent<S,T>(currentState, target, stateId));
                
            }
        });
    }

    /**
     * Saves the current currentState.
     */
    public void saveState() {
        stateManager.set(stateId, currentState);
        eventBus.fireEvent(new SaveStateEvent<S, T>(target, currentState, stateId));
    }

    public void clearState() {
        stateManager.clear(stateId);
    }
}
